package cs6238.server;

import java.io.File;
import java.io.IOException;
import java.security.Security;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import cs6238.common.CertificateHelper;
import cs6238.common.Configuration;

/**
 * Entry point for the server app
 *
 */
public class ServerMain {

	public static void main(String[] args) throws Exception{
		Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
		
		if(args.length == 1 && "clean".equals(args[0])){
			clean();
		}
		
		ServerMain server = new ServerMain();
		server.run();
	}
	
	private FileAndDelegateEntryTable _metadata;
	
	public ServerMain(){
		_metadata = new FileAndDelegateEntryTable(true);
	}
	
	public static void clean(){
		delete(FileAndDelegateEntryTable.DELEGATE_ENTRY_TABLE);
		delete(FileAndDelegateEntryTable.FILE_ENTRY_TABLE);
		
		ClientCertManager.deleteAllCertificates();
		FileManager.deleteAllFiles();
	}
	
	private static void delete(String filepath){
		File file = new File(filepath);
		if(file.exists()){
			file.delete();
		}
	}
	
	
	private void run() throws Exception{
		Configuration serverConfig = Configuration.loadServerSettings();
		int serverPort = Integer.parseInt(serverConfig.getSetting(Configuration.NETWORK_PORT));
		
		String keyStorePath = serverConfig.getSetting(Configuration.KEYSTORE_PATH);
		String keyStorePassword = serverConfig.getSetting(Configuration.KEYSTORE_PASSWORD);
		String trustStorePath = serverConfig.getSetting(Configuration.TRUSTSTORE_PATH);
		String trustStorePassword = serverConfig.getSetting(Configuration.TRUSTSTORE_PASSWORD);
		
		//System.setProperty("javax.net.debug", "all");
		System.setProperty("javax.net.ssl.keyStore", keyStorePath);
		System.setProperty("javax.net.ssl.keyStorePassword", keyStorePassword);
		System.setProperty("javax.net.ssl.trustStore", trustStorePath);
		System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword);

		SSLServerSocketFactory serverSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
		SSLServerSocket serverSocket = (SSLServerSocket) serverSocketFactory.createServerSocket(serverPort);
		serverSocket.setNeedClientAuth(true);

		System.out.println("Waiting for clients to connect...");
		while(true){
			try {
				//Wait for clients to join, then spin off a thread to deal with them
				SSLSocket clientSocket = (SSLSocket)serverSocket.accept();
				
				X509Certificate clientCert = (X509Certificate) clientSocket.getSession().getPeerCertificates()[0];
				String clientHostname = CertificateHelper.getHostname(clientCert);
				ClientCertManager.storeCertificate(clientCert);
				
				System.out.println( clientHostname + " just connected.");
				
				ClientHandlerCommunication clientHandler = new ClientHandlerCommunication(clientSocket, _metadata, clientHostname);
				Thread clientThread = new Thread(clientHandler);
				clientThread.start();
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	
	
}
